import os
import subprocess
import time
import traceback
import urllib
from urllib.parse import urlparse
import requests
from lib.lib import Config, comm_lib
from lib.var import static, dynamic
from lib.support_lib import download_file, is_valid_url

Info = {
    "name": "模块管理器",
    "id": "module_mgmt",
    "dependencies": [],
    "pip_dependencies": ["requests"],
    "linux_dependencies": []
}

default = {
    "modules_endpoint": "http://modules.afedium.furryaxw.top/index.json",
    "modules": {
        "core": {
            "id": "core",
            "type": "module",
            "method": "none",
            "source": "waiting",
        },
        "ws_server": {
            "id": "ws_server",
            "type": "module",
            "method": "none",
            "source": "local",
        },
        "external_handler": {
            "id": "external_handler",
            "type": "static",
            "method": "none",
            "source": "local",
        },
    },
    "waiting": [
        "fureye_driver"
    ],
}
config = Config("module_mgmt", default)
module_data = {}
site_url = ""


def install_modules(modules: list = None):
    if not static["online"]:
        return -1
    if modules: config.conf["waiting"].extend(modules)
    modules = config.conf["waiting"]
    for module in modules.copy():
        if module not in module_data.keys():
            print(f"无法找到模块：{module}")
            modules.remove(module)
        if module in static["modules"]:
            print(f"{module} 已安装")
            modules.remove(module)
        if module_data[module]["dependencies"]:
            for dependent in module_data[module]["dependencies"]:
                if dependent in list(static["modules"].keys()) + modules:
                    print(f"依赖已满足: {dependent}")
                else:
                    print(f"检测到依赖: {dependent}")
                    modules.append(dependent)
    config.conf["waiting"] = modules
    config.update()
    for module_n in modules.copy():
        try:
            print(f"正在安装: {module_n}")
            module = module_data[module_n]
            if is_valid_url(module["url"]):
                module_url = module["url"]
            else:
                module_url = urllib.parse.urljoin(site_url, module["url"])
            if module["type"] == "module":
                path = "module"
                download_file(module_url, path)
            elif module["type"] == "static":
                path = "static_module"
                download_file(module_url, path)
            config.conf["modules"][module_n] = {
                "id": module["id"],
                "type": module["type"],
                "method": "get",
                "source": module_url
            }
            try:
                modules.remove(module_n)
                static["modules"][module_n] = module["version"]
            except ValueError:
                pass
            except Exception:
                traceback.print_exc()
        except Exception:
            traceback.print_exc()
            return False
    print("安装完成，重启以应用更改。")
    config.conf["waiting"] = modules
    config.update()
    return True


def upgrade_modules(modules: list = None):
    if not static["online"]:
        return -1
    for module in modules:
        try:
            static["modules"].pop(module)
        except KeyError:
            pass
    return install_modules(modules)


def update_modules():
    if not static["online"]:
        return -1
    global module_data, site_url
    raw = get_json_from_url(config.conf["modules_endpoint"])
    site_url = raw["base_url"]
    for module in raw["modules"]:
        module_data[module["id"]] = module
    dynamic[Info["id"]]["data"] = module_data
    return module_data


def get_json_from_url(url):
    if not static["online"]:
        return -1
    try:
        response = requests.get(url)
        response.raise_for_status()
        data = response.json()
        return data
    except Exception:
        traceback.print_exc()
    return None


def git_clone(url, path='./'):
    if not (static["online"] and static["git_available"]):
        return -1
    if not os.path.isdir(path):
        print(f"错误: 目录 '{path}' 不存在。")
        return -1
    print(f"正在尝试克隆：{url}")
    return subprocess.run(
        ["git", "clone", url, path],
        check=True,
        capture_output=True,
        text=True
    )


def check_remote_update(path='./'):
    if not (static["online"] and static["git_available"]):
        return -1
    if not os.path.isdir(path):
        print(f"错误: 目录 '{path}' 不存在。")
        return -1
    subprocess.run(["git", "fetch"], cwd=path, check=True)
    raw = subprocess.run(
        ["git", "status", "-u no"],
        cwd=path,
        check=True,
        capture_output=True,
        text=True
    )
    output = raw.stdout
    if "Your branch is behind" in output:
        return "behind"
    elif "Your branch is up to date with" in output:
        return "up-to-date"
    elif "Your branch is ahead of" in output:
        return "ahead"
    else:
        return "unknown"


def command_handler(usr_comm):
    if usr_comm[0] == "update":
        return update_modules()
    elif usr_comm[0] == "install":
        return install_modules(usr_comm[1:])
    elif usr_comm[0] == "upgrade":
        return upgrade_modules(usr_comm[1:])
    else:
        return "未知指令(update/install)"


def __init__():
    dynamic[Info["id"]] = {}
    update_modules()
    comm_lib.register("module", command_handler)
    while True:
        time.sleep(0.1)
        try:
            if static["running"]["core"]:
                break
        except KeyError:
            pass
    if config.conf["modules"]["core"]["source"] == "waiting":
        if subprocess.run(["git", "rev-parse", "--is-inside-work-tree"],
                          check=True, capture_output=True, text=True
                          ).stdout.strip() == "true":
            source = subprocess.run(
                ["git", "config", "--get", "remote.origin.url"],
                check=True,
                capture_output=True,
                text=True
            ).stdout.strip()
            branch = subprocess.run(
                ["git", "branch", "--show-current"],
                check=True,
                capture_output=True,
                text=True
            ).stdout.strip()
            config.conf["modules"]["core"] = {
                "id": "core",
                "type": "module",
                "method": "git",
                "source": source,
                "branch": branch,
            }
            config.update()
        else:
            config.conf["modules"]["core"] = {
                "id": "core",
                "type": "module",
                "method": "none",
                "source": "local",
            }
            config.update()
    if config.conf["waiting"]:
        install_modules()
    static["features"].update({
        "module_mgmt": True,
    })
